home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d8 / pdriver5.arc / 82586.ASM < prev    next >
Assembly Source File  |  1989-12-17  |  23KB  |  852 lines

  1. i82586_version    equ    0
  2. DAN    equ    1
  3.  
  4. ;
  5. ; Code that is common between 82586 implementations.
  6. ;
  7.  
  8. ; Ported from Tim Krauskopf's micnet.asm, an assembly language
  9. ; driver for the MICOM-Interlan NI5210, by Russell Nelson.  Any bugs
  10. ; are due to Russell Nelson.
  11. ; Updated to version 1.08 Feb. 17, 1989 by Russell Nelson.
  12. ; Updated to support 1500 byte MTU April 27, 1989 By Brad Clements.
  13.  
  14. ; Copyright, 1988, 1989, Russell Nelson
  15.  
  16. ;   This program is free software; you can redistribute it and/or modify
  17. ;   it under the terms of the GNU General Public License as published by
  18. ;   the Free Software Foundation, version 1.
  19. ;
  20. ;   This program is distributed in the hope that it will be useful,
  21. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23. ;   GNU General Public License for more details.
  24. ;
  25. ;   You should have received a copy of the GNU General Public License
  26. ;   along with this program; if not, write to the Free Software
  27. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  28.  
  29. ;
  30. ;  Structure elements specific to the Intel 82586 chip
  31. ;
  32. BUF_COUNT EQU    28            ; number of buffers
  33. XMIT_MTU EQU    1500+14            ; size of xmit buffer (1500 MTU +
  34.                     ;   14 bytes for Ethernet headers
  35.  
  36. SCB    EQU    BASE_OFFSET + 10    ; system control block base
  37. CCBPTR    EQU    BASE_OFFSET + 26    ; offset of configure command block
  38. TCBPTR    EQU    BASE_OFFSET + 44    ; xmit CB offset
  39. TBDPTR    EQU    BASE_OFFSET + 60    ; xmit BD offset
  40. TBUFPTR    EQU    BASE_OFFSET + 68    ; xmit buffer offset
  41. FDBASE    EQU    TBUFPTR+XMIT_MTU    ; base addr for 30 frame descriptors
  42. FDSIZE  EQU     BUF_COUNT * 22
  43. BDBASE    EQU    FDBASE+FDSIZE        ; base address for 30 buffer descriptors
  44. BDASIZE    EQU     BUF_COUNT * 10
  45. BUFBASE    EQU    BDBASE+BDASIZE        ; base address for 30 200 byte buffers
  46. BUFFTOP EQU     BUFBASE+BUF_COUNT*200
  47. ISCPTR    EQU    BASE_OFFSET + 01feeh    ; my address for ISCP, points to SCB
  48. SCPTR    EQU    BASE_OFFSET + 01ff6h    ; hardwired address for SCP
  49.  
  50. if2
  51.         %out Buffer top is BUFFTOP
  52. if BUFFTOP > ISCPTR
  53.         %out Warning, buffers extend beyond ISCPTR, reduce BUF_COUNT.
  54. endif
  55. endif
  56. BDSTAT    EQU    0            ; status word in BD
  57. BDLINK    EQU    2            ; 16pointer to next BD
  58. BDPTR    EQU    4            ; 24pointer to actual buffer
  59. BDSIZE    EQU    8            ; size of the buffer
  60. ;
  61. SSTAT    EQU    0            ; status word for SCB
  62. SCOM    EQU    2            ; command word in SCB
  63. SCBL    EQU    4            ; 16pointer to command block list
  64. SRFA    EQU    6            ; 16pointer to receive frame list
  65. SERRS    EQU    8            ; 4 words of error counts
  66. ;
  67. FDSTAT    EQU    0            ; status word for frame
  68. FDEOL    EQU    2            ; end of FD list flag
  69. FDLINK    EQU    4            ; 16pointer to next FD
  70. FDPTR    EQU    6            ; 16pointer to list of BD's
  71. ;
  72. TSTAT    EQU    0            ; status word for xmit
  73. TCOM    EQU    2            ; command to transmit
  74. TLINK    EQU    4            ; 16pointer to next command (always ffff)
  75. TPTR    EQU    6            ; 16pointer to xmit TBD
  76. TTRIES    EQU    8            ; number of transmit retries
  77.  
  78.     public    rcv_modes
  79. rcv_modes    dw    4        ;number of receive modes in our table.
  80.         dw    0,0,0,rcv_mode_3
  81.  
  82. firstfd        dw    FDBASE        ; start of FD queue
  83. lastfd        dw    0        ; end of the FD chain
  84. lastbd        dw    0        ; end of the BD chain
  85. flag        dw    0
  86.  
  87.  
  88.     public    send_pkt
  89. send_pkt:
  90. ;enter with ds:si -> packet, cx = packet length.
  91. ;exit with nc if ok, or else cy if error, dh set to error number.
  92.     assume    ds:nothing
  93.     mov    ax,base_addr
  94.     mov    es,ax            ; base for board
  95.  
  96.     mov    word ptr es:[SCB+SCBL],TCBPTR; say where xmit command is
  97.  
  98.     cmp    cx,XMIT_MTU        ; Is this packet too large?
  99.     ja    send_pkt_toobig
  100.  
  101.     mov    dx,cx            ; save a copy, might be less than 60, ok
  102.  
  103.     cmp    dx,RUNT            ; minimum length for Ether
  104.     jnb    oklen
  105.     mov    dx,RUNT            ; make sure size at least RUNT
  106. oklen:
  107.     mov    di,TBUFPTR        ; start of xmit buffer
  108.  
  109. ;
  110. ;  check for previous xmit
  111. ;
  112. xwait:
  113.     mov    bx,word ptr es:[SCB+SCOM]    ; is command zeroed yet?
  114.     or    bx,bx
  115.     jnz    xwait                ; not there yet, wait for it
  116. ;
  117. ;  move the data using word moves.
  118. ;
  119.     call    movemem
  120. ;
  121. ;  put the correct size into the TDB
  122. ;
  123.     or    dx,08000h            ; end of frame bit flag
  124.     mov    word ptr es:[TBDPTR],dx        ; store it
  125.     mov    word ptr es:[TCBPTR],0        ; zero status wd
  126.     mov    word ptr es:[TCBPTR+TCOM],08004h; xmit command in TCB
  127.     mov    word ptr es:[SCB+SCOM],0100h    ; execute command
  128.  
  129.     call    doca
  130.  
  131.     clc
  132.     ret
  133. send_pkt_toobig:
  134.     mov    dh,NO_SPACE
  135.     stc
  136.     ret
  137.  
  138.  
  139. movemem:
  140. ;does the same thing as "rep movsb", only 50% faster.
  141. ;moves words instead of bytes, and handles the case of both addresses odd
  142. ;efficiently.  There is no way to handle one address odd efficiently.
  143. ;This routine always aligns the source address in the hopes that the
  144. ;destination address will also get aligned.  This is from Phil Karn's
  145. ;code from ec.c, a part of his NET package.  I bummed a few instructions
  146. ;out.
  147.     jcxz    movemem_cnte        ; If zero, we're done already.
  148.     test    si,1            ; Does source start on odd byte?
  149.     jz    movemem_adre        ; Go if not
  150.     movsb                ; Yes, move the first byte
  151.     dec    cx            ; Count that byte
  152. movemem_adre:
  153.     shr    cx,1            ; convert to word count
  154.     rep    movsw            ; Move the bulk as words
  155.     jnc    movemem_cnte        ; Go if the count was even
  156.     movsb                ; Move leftover last byte
  157. movemem_cnte:
  158.     ret
  159.  
  160.  
  161.     public    get_address
  162. get_address:
  163. ;get the address of the interface.
  164. ;enter with es:di -> place to get the address, cx = size of address buffer.
  165. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  166.     assume    ds:code
  167.     cmp    cx,EADDR_LEN        ;make sure that we have enough room.
  168.     jb    get_address_2
  169.     mov    cx,EADDR_LEN
  170.     mov    dx,io_addr        ; Get our IO base address.
  171.     cld
  172. get_address_1:
  173.     in    al,dx            ; get a byte of the eprom address
  174.     stosb                ; put it away
  175.     add    dx,GET_ADDR_INC        ; next register
  176.     loop    get_address_1        ; go back for rest
  177.     mov    cx,EADDR_LEN
  178.     clc
  179.     ret
  180. get_address_2:
  181.     stc
  182.     ret
  183.  
  184.  
  185. rcv_mode_3:
  186. ;receive mode 3 is the only one we support, so we don't have to do anything.
  187.     ret
  188.  
  189.  
  190.     public    set_multicast_list
  191. set_multicast_list:
  192. ;enter with es:di ->list of multicast addresses, cx = number of bytes.
  193. ;return nc if we set all of them, or cy,dh=error if we didn't.
  194.     mov    dh,NO_MULTICAST
  195.     stc
  196.     ret
  197.  
  198.  
  199.     public    get_multicast_list
  200. get_multicast_list:
  201. ;return with nc, es:di ->list of multicast addresses, cx = number of bytes.
  202. ;return cy, NO_ERROR if we don't remember all of the addresses ourselves.
  203. ;return cy, NO_MULTICAST if we don't implement multicast.
  204.     mov    dh,NO_MULTICAST
  205.     stc
  206.     ret
  207.  
  208.  
  209.     public    reset_interface
  210. reset_interface:
  211. ;reset the interface.
  212. ;we don't do anything.
  213.     ret
  214.  
  215.  
  216. ;called when we want to determine what to do with a received packet.
  217. ;enter with cx = packet length, es:di -> packet type.
  218.     extrn    recv_find: near
  219.  
  220. ;called after we have copied the packet into the buffer.
  221. ;enter with ds:si ->the packet, cx = length of the packet.
  222.     extrn    recv_copy: near
  223.  
  224.     extrn    count_in_err: near
  225.     extrn    count_out_err: near
  226.  
  227.     public    recv
  228. recv:
  229.     mov    flag, 1
  230. ;called from the recv isr.  All registers have been saved, and ds=cs.
  231. ;Upon exit, the interrupt will be acknowledged.
  232. recv1:
  233.     mov    ds,base_addr    ; base for board
  234.     assume    ds:nothing
  235.  
  236.     mov    ax,ds:[SCB+SSTAT]    ;get the status.
  237. recv_isr_1:
  238.     cmp    word ptr ds:[SCB+SCOM],0 ;are we done yet?
  239.     jne    recv_isr_1        ;no -- keep waiting.
  240.  
  241.     and    ax,0f000h        ;isolate the ACK bits.
  242.   if DAN
  243.     jz    recv_isr_2
  244.   endif
  245.     mov    ds:[SCB+SCOM],ax    ;make a command to
  246.                     ;acknowledge the interrupt.
  247.     call    doca
  248. recv_isr_2:
  249.     cmp    word ptr ds:[SCB+SCOM],0 ;are we done yet?
  250.     jne    recv_isr_2        ;no -- keep waiting.
  251.  
  252. ;  Get whatever packets are on the board
  253. ;
  254.     mov    bx,firstfd    ; get addr of first FD in list
  255.     mov    ax,[bx+FDSTAT]    ; status word of frame
  256.     test    ax,08000h    ; frame written?
  257.     jnz    okframe
  258.  
  259.     jmp    ru_start    ; no, restore receiver if necessary
  260. frame_bad:
  261.     call    count_in_err
  262. ptrupdate_j_1:
  263.     jmp    ptrupdate
  264.  
  265. ;  we have a frame, read it in
  266. ;
  267. okframe:
  268.     test    ax,02000h        ;check frame OK bit
  269.     jz    frame_bad        ;bad, fix it.
  270.     mov    si,[bx+FDPTR]        ;get pointer to buffer descriptor
  271.     xor    cx,cx            ;start with zero bytes.
  272. countbuf:                ;es:di is already set to receive packet
  273.     mov    dx,si            ;save a copy of current BD ptr
  274.     mov    ax,[si+BDSTAT]        ;get status and count word for BD
  275.     test    ax,04000h        ;is count field there?
  276.     jz    ptrupdate_j_1        ;no - we give up here.
  277.     add    cl,al            ;add the count into cx.
  278.     adc    ch,0
  279.     mov    si,[si+BDLINK]        ;go to next BD in list
  280.     test    ax,8000h        ;is this the last frame?
  281.     je    countbuf        ;no - keep counting.
  282.  
  283.     push    bx
  284.     push    cx
  285.  
  286.     mov    ax,cs            ;we need ds = code.
  287.     mov    ds,ax
  288.     assume    ds:code
  289.  
  290.     mov    es,base_addr        ;get a pointer to their type.
  291.     mov    di,es:[bx+FDPTR]    ;get pointer to buffer descriptor
  292.     mov    di,es:[di+BDPTR]    ;get offset of data
  293.     add    di,EADDR_LEN+EADDR_LEN    ;skip the ethernet addreses and
  294.                     ;  point to the packet type.
  295.  
  296.     call    recv_find        ;look up our type.
  297.  
  298.     pop    cx
  299.     pop    bx
  300.     mov    ds,base_addr        ;restore ds to the board.
  301.     assume    ds:nothing
  302.  
  303.     mov    ax,es            ;is this pointer null?
  304.     or    ax,di
  305.     je    ptrupdate        ;yes - just free the frame.
  306.  
  307.     push    cx
  308.     push    es            ;remember where the buffer pointer is.
  309.     push    di
  310.   if DAN
  311.     push    cx
  312.   endif
  313.  
  314.     mov    si,[bx+FDPTR]        ;get pointer to buffer descriptor
  315. copybuf:
  316.     mov    dx,si            ;save a copy of current BD ptr
  317.     xor    ch,ch            ;200 bytes is largest this can be
  318.     mov    cl,[si+BDSTAT]        ;get count word for BD
  319.     mov    si,[si+BDPTR]        ;get offset of data
  320.   if DAN
  321.     pop    ax
  322.     sub    ax, cx
  323.     jc    copydone
  324.     push    ax
  325.   ENDIf
  326.     call    movemem
  327.     mov    si,dx            ;get back current BD ptr
  328.     test    [si+BDSTAT],8000h    ;check EOF bit
  329.     mov    si,[si+BDLINK]        ;go to next BD in list
  330.     jz    copybuf            ;not done, keep copying it.
  331.  
  332.   if DAN
  333.     pop    cx
  334. copydone:
  335.   endif
  336.     pop    si            ;now give the frame to the client.
  337.     pop    ds
  338.     pop    cx
  339.     assume    ds:nothing
  340.  
  341.     call    recv_copy
  342. ;
  343. ;  we are done with the frame, do the list management
  344. ;
  345. ptrupdate:
  346.     push    cs
  347.     pop    ds
  348.     assume    ds:code
  349.     mov    es,base_addr        ; reload board segment
  350.  
  351.     mov    si,es:[bx+FDPTR]    ; first BD in frame list
  352. nextbd:
  353.     mov    cx,es:[si+BDSTAT]    ; count word for BD, EOF bit
  354.     test    cx,08000h        ; EOF bit, if set, save si in lastbd
  355.     jnz    dolastbd
  356.     mov    word ptr es:[si+BDSTAT],0 ; clear status word, EOF bit
  357.     cmp    si,lastbd        ; see if we are wrapping
  358.     jz    dolastbd        ; yes, just undo it
  359.     mov    si,es:[si+BDLINK]    ; follow link
  360.     jmp    nextbd
  361. dolastbd:
  362.     mov    di,lastbd        ; where end of BD list is now
  363.     mov    lastbd,si        ; store last known BD
  364.     mov    word ptr es:[si+BDSIZE],08000h+200    ; end of list here
  365.     mov    word ptr es:[si+BDSTAT],0 ; clear status word, EOF bit
  366. ; size field for not end of list
  367.     mov    word ptr es:[di+BDSIZE],200    ; remove old end-of-list
  368.  
  369. ;
  370. ;  update the FD list flags, new end-of-list
  371. ;
  372.     mov    word ptr es:[bx+FDEOL],08000h    ; store new EOL
  373.     mov    word ptr es:[bx+FDSTAT],0    ; clear status word for frame
  374.     mov    di,lastfd        ; get old end-of-list
  375.     mov    word ptr es:[di+FDEOL],0 ; zero old one
  376.     mov    lastfd,bx        ; update stored pointer
  377.     mov    si,es:[bx+FDLINK]    ; where next fd is
  378.     mov    firstfd,si        ; store that info for next time
  379.   if DAN
  380.     jmp    recv1
  381.   endif
  382.  
  383. ru_start:
  384. ; re-start receive unit
  385. ;
  386. ;  check to see if the receiver went off because of no resources
  387. ;  and restart receiver if necessary
  388. ;
  389.     push    cs
  390.     pop    ds
  391.     mov    es,base_addr
  392.     mov    ax,es:[SCB+SSTAT]    ; status word for SCB
  393.     and    ax,070h        ; receiver status
  394.     cmp    al,020h        ; receiver has no resources
  395.     jnz    hasres
  396.   if DAN
  397.     cmp    flag, 1
  398.     jnz    ru_start1
  399.     mov    flag, 0
  400.     jmp    recv1
  401.   endif
  402.  
  403. ru_start1:
  404.     call    count_out_err
  405. ;
  406. ;  setup lists for starting the RU on the chip
  407. ;  we know that there isn't anything in the buffer that we want
  408. ;
  409.  
  410.     mov    bx,firstfd    ; get first FD on free list (assume free)
  411.     mov    word ptr es:[SCB+SRFA],bx    ; put into SCB
  412.     mov    si,lastbd    ; pointer to a BD, end of chain
  413.     mov    ax,word ptr es:[si+BDLINK]    ; pointer to next BD
  414.     mov    word ptr es:[bx+FDPTR],ax    ; set to start of BDs
  415. ;
  416. ;
  417. ;  Start the RU, doesn't need CB, only SCB parms.
  418. ;   command, to start receiving again
  419. ;
  420.     mov    word ptr es:[SCB+SSTAT],0    ; clear status word
  421.     mov    word ptr es:[SCB+SCOM],010h    ; start RU
  422.     call    doca
  423. hasres:
  424. recv_isr_end:
  425.     cmp    word ptr es:[SCB+SCOM],0 ;are we done yet?
  426.     jne    recv_isr_end        ;no -- keep waiting.
  427.     ret
  428.  
  429.  
  430.     public    recv_exiting
  431. recv_exiting:
  432. ;called from the recv isr after interrupts have been acknowledged.
  433. ;Only ds and ax have been saved.
  434.     assume    ds:nothing
  435.     ret
  436.  
  437.  
  438.     public    set_address
  439. set_address:
  440.     assume    ds:nothing
  441. ;enter with ds:si -> Ethernet address, CX = length of address.
  442. ;exit with nc if okay, or cy, dh=error if any errors.
  443.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  444.     je    set_address_4
  445.     mov    dh,BAD_ADDRESS
  446.     stc
  447.     jmp    short set_address_done
  448. set_address_4:
  449.  
  450. ;  Next step, load our address into the board
  451. ;     reuses the space that the configure command used, with different command
  452. ;
  453.     mov    es,base_addr        ; set to base address
  454.     mov    word ptr es:[SCB+SCBL],CCBPTR    ; say where conf command is
  455.  
  456.     mov    di,CCBPTR        ; start of config command block
  457.     xor    ax,ax
  458.     stosw                ; zero status word for commmand
  459.     mov    ax,8001h        ; IA setup command + EL
  460.     stosw
  461.     xor    ax,ax
  462.     dec    ax
  463.     stosw                ; set link value to -1 (unused)
  464.  
  465.     rep    movsb            ; move their ethernet address in.
  466. ;
  467. ;  start the IA setup command
  468. ;
  469.     mov    word ptr es:[SCB+SCOM],0100h    ; do-command command
  470.     call    doca
  471.     xor    cx,cx            ; timeout
  472. set_address_1:
  473.     mov    ax,word ptr es:[CCBPTR]    ; get status word
  474.     test    ax,08000h        ; is command complete?
  475.     loopz    set_address_1
  476.     jnz    set_address_okay
  477.     stc
  478.     mov    dh,-1            ; no error in the list applies.
  479.     jmp    short set_address_done
  480. set_address_okay:
  481.     mov    cx,EADDR_LEN        ;return their address length.
  482.     clc
  483. set_address_done:
  484.     push    cs
  485.     pop    ds
  486.     assume    ds:code
  487.     ret
  488.  
  489.  
  490. end_resident    label    byte
  491.  
  492. timeout_msg    db    "Timed out while initializing the board.",CR,LF,'$'
  493. int_no_name    db    "Interrupt number ",'$'
  494. io_addr_name    db    "I/O port ",'$'
  495. base_addr_name    db    "Memory address ",'$'
  496. our_address    db    6 dup(?)    ;temporarily hold our address
  497.  
  498. tdr_ok_msg    db    "TDR Ok",CR,LF,'$'
  499. tdr_none_msg    db    "Your Ethernet card doesn't seem to be plugged in.",CR,LF,'$'
  500. tdr_open_msg    db    " clocks away is an OPEN",CR,LF,'$'
  501. tdr_short_msg    db    " clocks away is a SHORT",CR,LF,'$'
  502.  
  503. mem8_16        db    2        ; 1 for 16k, 2 for 8k
  504.  
  505.     extrn    set_recv_isr: near
  506.  
  507.  
  508. ;enter with si -> argument string, di -> word to store.
  509. ;if there is no number, don't change the number.
  510.     extrn    get_number: near
  511.  
  512. ;enter with dx:ax = number to print.
  513.     extrn    hexout: near, decout: near
  514.  
  515. ;enter with ax = segment of memory to test, cx = number of bytes to test.
  516. ;exit with ne, bx->failing byte if the memory test failed.
  517.     extrn    memory_test: near
  518.  
  519.     public    parse_args
  520. parse_args:
  521.     mov    di,offset int_no
  522.     mov    bx,offset int_no_name
  523.     call    get_number
  524.     mov    di,offset io_addr
  525.     mov    bx,offset io_addr_name
  526.     call    get_number
  527.     mov    di,offset base_addr
  528.     mov    bx,offset base_addr_name
  529.     call    get_number
  530.     sub    base_addr,BASE_OFFSET shr 4
  531.     ret
  532.  
  533.  
  534. timeout_error:
  535.     mov    dx,offset timeout_msg
  536.     jmp    short error
  537. error:
  538.     mov    ah,9
  539.     int    21h
  540.     stc
  541.     ret
  542.  
  543. ;
  544. ;  data for configuring and setting up the board
  545. ;
  546. ;  chip always looks at SCP for config info which points to ISCP for the
  547. ;  pointer to the CONTROL BLOCK which handles everything from there.
  548. ;  Kind of indirect, but it works.
  549. ;
  550. SCP    DB    BUS_TYPE    ; bus use flag (0=16 bit, 1=8 bit).
  551.     DB    5 DUP(0)    ; unused
  552.     DW    ISCPTR        ; 24pointer to ISCP offset
  553.     DW    0        ; high part
  554. ;
  555. ; Intermediate SCP
  556. ;
  557. ISCP    DW    1        ; busy flag
  558.     DW    SCB        ; 16pointer to SCB
  559.     DW    0,0        ; base for all 16 pointers, lo, hi
  560.                 ; board is hardwired to 0 for these values
  561. ;
  562. ; Configuration block for 82586, this comprises one config command
  563. ;  Parameters taken from MICOM driver
  564. ;
  565. CBCONF    DW    0        ; status word
  566.     DW    8002H        ; end of command list + configure command
  567.     DW    0ffffh        ; link to next command (not used)
  568.     DW    080CH        ; fifo=8, byte count=C
  569.     DW    2E00H        ; important! Addr (AL) not inserted on the fly!
  570.     DW    6000H        ; IFS = 60h
  571.     DW    0F200H        ; retry=F, slot time=200h
  572.     DW    0        ; flags, set to 1 for promiscuous
  573.     DW    40H        ; min frame length=40h
  574. ;
  575. ; CB for xmit, followed by BD for xmit, copied together
  576. ;
  577. TCB    DW    0        ; status word
  578.     DW    08004H        ; command word for xmit + EL
  579.     DW    0ffffh        ; no command link
  580.     DW    TBDPTR        ; 16pointer to xmit BD
  581.     DW    0,0,0,0        ; no addressing used here
  582. ;
  583. ; BD template for xmit
  584. TBD    DW    0
  585.     DW    0        ; next BD pointer, unused
  586.     DW    TBUFPTR        ; 24pointer to xmit buffer
  587.     DW    0        ; high part of pointer
  588.  
  589.     public    etopen
  590. etopen:
  591. ;  Initialize the Ethernet board, set receive type.
  592. ;
  593. ;  check for correct EPROM location
  594. ;
  595.     call    check_board
  596.  
  597. ;  Initialize the Ethernet board, set receive type.
  598. ;
  599. ;  Install 8K SCP, we only use 8K bytes no matter what
  600. ;
  601.     mov    es,base_addr    ; set to base address
  602.     mov    di,SCPTR
  603.     mov    si,offset SCP    ; get pre-set values
  604.     mov    cx,5        ; 5 words
  605.     rep    movsw        ; install SCP
  606. ;
  607. ;  Intermediate SCP
  608. ;
  609.     mov    si,offset ISCP    ; addr of pre-set values
  610.     mov    di,ISCPTR
  611.     mov    cx,4        ; 4 words
  612.     rep    movsw        ; install ISCP
  613.     jmp    config_5210
  614. try_16:
  615. ;
  616. ;  Install for 16K SCP, even though equates are for 8K.
  617. ;
  618.     mov    si,offset SCP    ; get pre-set values
  619.     mov    di,SCPTR+2000h    ; offset for 16K board
  620.     mov    cx,5        ; 5 words
  621.     rep    movsw        ; install SCP
  622. config_5210:
  623.  
  624.   ifdef IORESET
  625. ;
  626. ;  Reset the chip
  627. ;
  628.     loadport
  629.     setport    IORESET
  630.     out    dx,al
  631. ;
  632. ;  Turn off interrupts, I don't want them
  633. ;
  634.   ifdef IOINTOF
  635.     loadport
  636.     setport IOINTOF
  637.     out    dx,al
  638.   endif
  639. ;
  640. ;  Disconnect from network
  641.     loadport
  642.     setport    IODIS
  643.     out    dx,al
  644.   endif
  645. ;
  646. ;  Issue a CA to initialize the chip after reset
  647. ;
  648.     call    lbca
  649. ;
  650. ;  configure 82586
  651. ;
  652.     mov    si,offset CBCONF    ; configure command
  653.     mov    di,CCBPTR        ; where command will reside
  654.     mov    cx,9
  655.     rep    movsw            ; copy to board
  656. ;
  657. ;  issue the configure command
  658. ;
  659.     mov    word ptr es:[SCB+SCOM],0100h    ; do-command command
  660.     mov    word ptr es:[SCB+SCBL],CCBPTR    ; where conf command is
  661.     mov    word ptr es:[SCB+SERRS],0    ; zero errs field
  662.     mov    word ptr es:[SCB+SERRS+2],0    ; zero errs field
  663.     mov    word ptr es:[SCB+SERRS+4],0    ; zero errs field
  664.     mov    word ptr es:[SCB+SERRS+6],0    ; zero errs field
  665.     call    lbca
  666.     xor    cx,cx            ; timeout
  667. waitconf:
  668.     mov    ax,word ptr es:[CCBPTR]    ; get status word
  669.     test    ax,08000h        ; is command complete?
  670.     loopz    waitconf
  671.     jnz    confok            ; if we didn't timeout, we're okay.
  672.     dec    mem8_16            ; Did we try both 8K and 16K?
  673.     jnz    try_16            ; if we only did the 8K, try 16K.
  674.     jmp    timeout_error
  675. confok:
  676. ;
  677. ;  Ask the board for the Ethernet address, and then use set_address to set it.
  678. ;
  679.     mov    dx,io_addr        ; Get our IO base address
  680.     mov    si,offset our_address
  681.     mov    cx,EADDR_LEN
  682. store_address_1:
  683.     in    al,dx            ; get a byte of the eprom address
  684.     mov    [si],al            ; put it away
  685.     inc    si
  686.     add    dx,GET_ADDR_INC        ; next register
  687.     loop    store_address_1        ; go back for rest
  688.  
  689.     mov    si,offset our_address
  690.     mov    cx,EADDR_LEN
  691.     call    set_address
  692.     jnc    store_address_2
  693.     jmp    timeout_error
  694. store_address_2:
  695. ;
  696. ;  IA sent, setup all of the other data structures on the board
  697. ;  start with xmit command descriptors
  698. ;
  699.     mov    si,offset TCB        ; template for xmit
  700.     mov    di,TCBPTR        ; where it goes on board
  701.     mov    cx,12            ; copies CB and BD for xmit
  702.     rep    movsw
  703. ;
  704. ;  Set up frame and buffer descriptors, 30 each
  705. ;
  706.     mov    cx,BUF_COUNT        ; # of FDs
  707.     mov    di,FDBASE        ; base addr for FDs
  708. fdloop:
  709.     xor    ax,ax
  710.     mov    bx,di            ; save pointer
  711.     stosw                ; clear status wd
  712.     stosw                ; clear EL field
  713.     add    bx,22            ; points to next one
  714.     mov    es:[di],bx        ; put in link ptr
  715.     inc    di
  716.     inc    di
  717.     dec    ax
  718.     stosw                ; clear BD ptr to -1
  719.     add    di,14
  720.     loop    fdloop
  721.  
  722.     sub    di,20            ; point back to last EL field
  723.     mov    ax,08000h        ; end of list
  724.     stosw                ; put into last FD
  725.     sub    di,4            ; back to beginning of last FD
  726.     mov    lastfd,di        ; save the pointer
  727.     mov    word ptr es:[di+FDLINK],FDBASE    ; make list circular,
  728.                         ; from last to first
  729.  
  730.     mov    ax,BDBASE        ; first BD
  731.     mov    word ptr es:[FDBASE+FDPTR],ax    ; put it in the first FD frame
  732. ;
  733. ;  now BDs
  734.     mov    cx,BUF_COUNT
  735.     mov    di,BDBASE        ; start of BD area
  736.     mov    dx,BUFBASE        ; start of buffer area
  737. bdloop:
  738.     xor    ax,ax
  739.     mov    bx,di            ; save pointer
  740.     stosw                ; zero status field
  741.     add    bx,10            ; point to next record
  742.     mov    es:[di],bx        ; put in link ptr
  743.     inc    di
  744.     inc    di
  745.     mov    es:[di],dx        ; address of buffer, lo part
  746.     inc    di
  747.     inc    di
  748.     stosw                ; zero out high part
  749.     mov    ax,200
  750.     stosw                ; store length field
  751.     add    dx,ax            ; add in length of buffer, updates ptr
  752.     loop    bdloop
  753.  
  754.     sub    di,2            ; back to last BD size field
  755.     mov    ax,08000h+200        ; end of list + 200
  756.     stosw                ; mark end of list
  757.     sub    di,8            ; back to last BDLINK field
  758.     mov    ax,BDBASE
  759.     stosw                ; put link to beginning of list here
  760.     sub    di,4            ; back to beginning of last BD
  761.     mov    lastbd,di        ; save pointer to end of list
  762.   ifdef IOENA
  763. ;
  764. ;  configure to connect to network
  765. ;
  766.     loadport
  767.     setport    IOENA            ; enable network
  768.     out    dx,al            ; any al value
  769.   endif
  770. ;
  771. ; Test to see if the network is okay.
  772. ;
  773.     mov    di,CCBPTR        ; start of config command block
  774.     xor    ax,ax            ; zero status word for commmand
  775.     stosw
  776.     mov    ax,8005h        ; TDR command + EL
  777.     stosw
  778.     xor    ax,ax
  779.     dec    ax
  780.     stosw                ; set link value to -1 (unused)
  781.     inc    ax
  782.     stosw                ; zero time result.
  783.  
  784.     mov    word ptr es:[SCB+SCOM],0100h    ; do-command command
  785.  
  786.     call    lbca
  787.  
  788.     xor    cx,cx            ; timeout
  789. do_tdr_1:
  790.     mov    ax,word ptr es:[CCBPTR]    ; get status word
  791.     test    ax,08000h        ; is command complete?
  792.     loopz    do_tdr_1
  793.     mov    ax,word ptr es:[CCBPTR+6]
  794.     jnz    do_tdr_2
  795.     mov    ax,2000h        ; treat a timeout as an open
  796. do_tdr_2:
  797.     test    ax,8000h
  798.     mov    dx,offset tdr_ok_msg
  799.     jne    do_tdr_3
  800.     mov    dx,offset tdr_short_msg
  801.     test    ax,2000h
  802.     je    do_tdr_4
  803.     mov    dx,offset tdr_none_msg
  804.     cmp    ax,2000h
  805.     je    do_tdr_3
  806.     mov    dx,offset tdr_open_msg
  807. do_tdr_4:
  808.     push    dx
  809.     and    ax,2048-1
  810.     xor    dx,dx
  811.     call    decout
  812.     pop    dx
  813. do_tdr_3:
  814.     mov    ah,9
  815.     int    21h
  816.  
  817. ;
  818. ;  minor detail, but important
  819. ;  Change SCB command block pointer to setup for xmit commands
  820. ;      = only commands needed when operational
  821. ;
  822.     mov    word ptr es:[SCB+SCBL],TCBPTR    ; where xmit command is
  823. ;
  824. ;  Start the RU, doesn't need CB, only SCB parms.
  825. ;   command, to start receiving
  826. ;
  827.     mov    word ptr es:[SCB],0        ; clear status word
  828.     mov    word ptr es:[SCB+SRFA],FDBASE    ; set to frame descriptors
  829.     mov    word ptr es:[SCB+SCOM],010h    ; start RU
  830.     call    lbca
  831. ;
  832. ; Now reset CX, FR, CNA, and RNR so that we don't get a spurious interrupt.
  833. ;
  834. store_ack_1:
  835.     cmp    word ptr es:[SCB+SCOM],0 ;are we done yet?
  836.     jne    store_ack_1        ;no -- keep waiting.
  837.  
  838.     mov    ax,es:[SCB+SSTAT]    ;get the status.
  839.     and    ax,0f000h        ;isolate the ACK bits.
  840.     mov    es:[SCB+SCOM],ax    ;make a command to
  841.                     ;acknowledge the interrupt.
  842.     call    doca
  843. ;
  844. ; Now hook in our interrupt
  845. ;
  846.     call    set_recv_isr
  847.  
  848.     mov    dx,offset end_resident
  849.     clc
  850.     ret
  851.  
  852.